home *** CD-ROM | disk | FTP | other *** search
- /*
- * hashfn.c
- *
- * Identification:
- * $Header: /private/postgres/src/utils/hash/RCS/hashfn.c,v 1.5 1992/03/30 00:07:41 mer Exp $
- *
- */
- #include "utils/hsearch.h"
-
- /*
- Assume that we've already split the bucket to which this
- key hashes, calculate that bucket, and check that in fact
- we did already split it.
- */
- int
- string_hash(key,keysize)
- char * key;
- int keysize;
- {
- int h;
- register unsigned char *k = (unsigned char *) key;
-
- h = 0;
- /*
- * Convert string to integer
- */
- while (*k)
- h = h * PRIME1 ^ (*k++ - ' ');
- h %= PRIME2;
-
- return (h);
- }
-
-
- tag_hash(key,keysize)
- int * key;
- int keysize;
- {
- register int h = 0;
-
- /*
- * Convert tag to integer; Use four byte chunks in a "jump table"
- * to go a little faster. Currently the maximum keysize is 16
- * (mar 17 1992) I have put in cases for up to 24. Bigger than
- * this will resort to the old behavior of the for loop. (see the
- * default case).
- */
- switch (keysize)
- {
- case 6*sizeof(int):
- h = h * PRIME1 ^ (*key);
- key++;
- /* fall through */
-
- case 5*sizeof(int):
- h = h * PRIME1 ^ (*key);
- key++;
- /* fall through */
-
- case 4*sizeof(int):
- h = h * PRIME1 ^ (*key);
- key++;
- /* fall through */
-
- case 3*sizeof(int):
- h = h * PRIME1 ^ (*key);
- key++;
- /* fall through */
-
- case 2*sizeof(int):
- h = h * PRIME1 ^ (*key);
- key++;
- /* fall through */
-
- case sizeof(int):
- h = h * PRIME1 ^ (*key);
- key++;
- break;
-
- default:
- for(; keysize > (sizeof(int)-1); keysize -= sizeof(int), key++)
- h = h * PRIME1 ^ (*key);
- /*
- * now let's grab the last few bytes of the tag if the tag
- * has (size % 4) != 0 (which it sometimes will on a sun3).
- */
- if (keysize)
- {
- char *keytmp = (char *)key;
-
- switch (keysize)
- {
- case 3:
- h = h * PRIME1 ^ (*keytmp);
- keytmp++;
- /* fall through */
- case 2:
- h = h * PRIME1 ^ (*keytmp);
- keytmp++;
- /* fall through */
- case 1:
- h = h * PRIME1 ^ (*keytmp);
- break;
- }
- }
- break;
- }
-
- h %= PRIME2;
- return (h);
- }
-
- /*
- * This is INCREDIBLY ugly, but fast.
- * We break the string up into 8 byte units. On the first time
- * through the loop we get the "leftover bytes" (strlen % 8).
- * On every other iteration, we perform 8 HASHC's so we handle
- * all 8 bytes. Essentially, this saves us 7 cmp & branch
- * instructions. If this routine is heavily used enough, it's
- * worth the ugly coding
- */
- int
- disk_hash(key)
- char *key;
- {
- register int n = 0;
- register char *str = key;
- register int len = strlen(key);
- register int loop;
-
- #define HASHC n = *str++ + 65599 * n
-
- if (len > 0) {
- loop = (len + 8 - 1) >> 3;
-
- switch(len & (8 - 1)) {
- case 0: do { /* All fall throughs */
- HASHC;
- case 7: HASHC;
- case 6: HASHC;
- case 5: HASHC;
- case 4: HASHC;
- case 3: HASHC;
- case 2: HASHC;
- case 1: HASHC;
- } while (--loop);
- }
-
- }
- return(n);
- }
-
-
-